#include "RtBase.h"
#include "dboci.h"

#ifdef __ORACLE__
/*--------------------------------------------------------------*/
/*                                                              */
/*      class CDBException_                                     */
/*                                                              */
/*--------------------------------------------------------------*/
CDBException_::CDBException_()
{
}

CDBException_::~CDBException_()
{
}

void CDBException_::BuildErrorString(short nRetCode, OCIEnv *envhp)
{
	short status;
	
	Empty();
	
	m_nRetCode = (int) nRetCode;
	
	if(envhp)
		if((status = OCIErrorGet(
			(dvoid*)envhp,
			(ub4) 1,
			(text*) NULL,
			(sb4*) &m_nRetCode,
			(text*) m_szError,
			(ub4) sizeof(m_szError),
			(ub4) OCI_HTYPE_ENV)) != OCI_SUCCESS)
		{
			strcpy((char*)m_szError,
				"Can't get error message by calling OCIErrorGet.\n");
		}
}

void CDBException_::BuildErrorString(short nRetCode, OCIError *errhp)
{
	short status;
	
	Empty();
	
	m_nRetCode = (int) nRetCode;
	
	if(errhp)
		if((status = OCIErrorGet( 
			(dvoid*)errhp,
			(ub4) 1,
			(text*) NULL,
			(sb4*) &m_nRetCode,
			(text*) m_szError,
			(ub4) sizeof(m_szError),
			(ub4) OCI_HTYPE_ERROR)) != OCI_SUCCESS)
		{
			strcpy((char*)m_szError, 
				"Can't get error message by calling OCIErrorGet.\n");
		}
}

void CDBException_::SetErrorString(short nRetCode, LPCSTR lpszError)
{
	m_nRetCode = nRetCode;
	strcpy((char*)m_szError, lpszError);
}

void CDBException_::Empty()
{
	m_nRetCode = DB_SUCCESS;
	memset(m_szError, 0, _MAX_ERRMESSAGE);
}

void _DB_ThrowException(short nRetCode, OCIEnv *envhp)
{
	CDBException_* e = new CDBException_();
	e->BuildErrorString(nRetCode, envhp);
	throw(e);
}


void _DB_ThrowException(short nRetCode, OCIError *errhp)
{
	CDBException_* e = new CDBException_();
	e->BuildErrorString(nRetCode, errhp);
	throw(e);
}

void _DB_ThrowException(short nRetCode, LPCSTR lpszError)
{
	CDBException_* e = new CDBException_();
	e->SetErrorString(nRetCode, lpszError);
	throw(e);
}

/*--------------------------------------------------------------*/
/*																*/
/* 	class CDatabase_ 											*/
/*																*/
/*--------------------------------------------------------------*/
CDatabase_::CDatabase_()
{
	m_envhp = (OCIEnv*)		0;
	m_errhp = (OCIError*)	0;
	m_seshp = (OCISession*)	0;
	m_srvhp = (OCIServer*)	0;
	m_svchp = (OCISvcCtx*)	0;
	m_stmhp = (OCIStmt*)	0;
	
	memset(m_dbserver, 0, _MAX_DBLENGTH);
	memset(m_database, 0, _MAX_DBLENGTH);
	memset(m_username, 0, _MAX_DBLENGTH);
	memset(m_password, 0, _MAX_DBLENGTH);
	memset(m_sqlstmt,  0, _MAX_SQLLENGTH);
	
	m_bConnected = FALSE;	//gary0210
	
	////////////////Add for Statment Binding/////////////
	m_pDBPreStmt = NULL;
	m_bSQLStmtPrepared = false;
	m_bSQLStmtBind = false;	
	m_cursor = NULL;
	m_init = 0;
}

CDatabase_::~CDatabase_()
{
	Cleanup();	//gary0210
}


int CDatabase_::Init()
{
	/*if(m_init !=0 || m_init != 3)
		return m_init;*/

	int status;
	if(m_init ==0)
	{
		if((status = OCIInitialize( 
		//(ub4) OCI_DEFAULT,
		(ub4) OCI_OBJECT, 
		(dvoid*) 0,
		(dvoid* (*)(dvoid*, size_t)) 0,
		(dvoid* (*)(dvoid*, dvoid*, size_t)) 0,
		(void (*)(dvoid*, dvoid*)) 0 )) != OCI_SUCCESS)
			return status;
		else
			m_init++;
	}
	
	if(m_init == 1)
	{
		if((status = OCIEnvInit( (OCIEnv**) &m_envhp, 
		OCI_DEFAULT,
		(size_t) 0, 
		(dvoid**) 0 )) != OCI_SUCCESS)
		{
			if(m_envhp)
			{
				OCIHandleFree((dvoid*)m_envhp, OCI_HTYPE_ENV);
				m_envhp=NULL;
			//	RT_INFO_TRACE("here");
			}

			return status;
		}
		else
			m_init++;
	}

	if(m_init ==2)
	{
		if((status=OCIHandleAlloc( (dvoid*) m_envhp,
		(dvoid**) &m_errhp,
		OCI_HTYPE_ERROR,
		(size_t) 0, 
		(dvoid**) 0 )) != OCI_SUCCESS)
			return status;
		else
			m_init++;
	}
	RT_ASSERTE(m_init == 3);
	return OCI_SUCCESS;
}
/* Called to initialize the Oracle OCI enviornment, establish a connection
to a server, and authorize a user to perform actions against a database */
int  CDatabase_::Open( LPBYTE dbserver,
					  LPBYTE database, 
					  LPBYTE username, 
					  LPBYTE password,
					  BOOL  bReadOnly )
{
	int	status;
	
	//gary0210
	if(m_bConnected)
	{
		if(strcmp((char*)m_database, (char*)database) == 0 &&
			strcmp((char*)m_username, (char*)username) == 0 &&
			strcmp((char*)m_password, (char*)password) == 0)
		{
			return DB_SUCCESS;
		}
		/*else
		{
			Cleanup();
		}*/
	}
	
	if((status = Init()) != OCI_SUCCESS)
	{
		//CM_INFO_TRACE("m_init="<<m_init<<",status="<<status);
		_DB_ThrowException(status, "Can't Init OCI environment");
	}
		
	Cleanup();

	strcpy((char*)m_dbserver, (char*)dbserver);
	strcpy((char*)m_database, (char*)database);
	strcpy((char*)m_username, (char*)username);
	strcpy((char*)m_password, (char*)password);
	m_bReadOnly = bReadOnly;
	
	/* allocates and initializes OCIServer handle */
	if((status = OCIHandleAlloc( (dvoid*) m_envhp,
		(dvoid**) &m_srvhp,
		OCI_HTYPE_SERVER,
		(size_t) 0, 
		(dvoid**) 0 )) != OCI_SUCCESS)
	{
        _DB_ThrowException(status, m_envhp);
	}
	
	/* allocates and initializes OCISvcCtx handle */
	if((status = OCIHandleAlloc( (dvoid*) m_envhp,
		(dvoid**) &m_svchp,
		OCI_HTYPE_SVCCTX,
		(size_t) 0, 
		(dvoid**) 0 )) != OCI_SUCCESS)
	{
        _DB_ThrowException(status, m_envhp);
	}
	
	/* attach to a database(server), initialize server context handle */
	if((status = OCIServerAttach( 
		m_srvhp, m_errhp,
		(text*)m_database, 
		strlen((char*)m_database),
		0 )) != OCI_SUCCESS)
	{
		_DB_ThrowException(status, m_errhp);
	}
	
	/* set attribute server context in the service context */
	if((status = OCIAttrSet(
		(dvoid*) m_svchp,
		OCI_HTYPE_SVCCTX,
		(dvoid*) m_srvhp, 
		(ub4) 0,
		OCI_ATTR_SERVER,
		m_errhp)) != OCI_SUCCESS)
	{
		_DB_ThrowException(status, m_errhp);
	}
	
	/* allocates and initializes OCISession handle */
	if((status = OCIHandleAlloc( 
		(dvoid*) m_envhp,
		(dvoid**) &m_seshp,
		OCI_HTYPE_SESSION,
		(size_t) 0, 
		(dvoid**) 0 )) != OCI_SUCCESS)
	{
		_DB_ThrowException(status, m_envhp);
	}
	
	/* set attribute username in the session */
	if((status = OCIAttrSet( 
		(dvoid*) m_seshp,
		(ub4) OCI_HTYPE_SESSION,
		(dvoid*) m_username,
		(ub4) strlen((char*)m_username),
		(ub4) OCI_ATTR_USERNAME,
		m_errhp )) != OCI_SUCCESS)
	{
		_DB_ThrowException(status, m_errhp);
	}
	
	/* set attribute password in the session */
	if((status = OCIAttrSet( (dvoid*) m_seshp,
		(ub4) OCI_HTYPE_SESSION,
		(dvoid*) m_password,
		(ub4) strlen((char*)m_password),
		(ub4) OCI_ATTR_PASSWORD,
		m_errhp )) != OCI_SUCCESS)
	{
		_DB_ThrowException(status, m_errhp);
	}
	
	/* create and begins a user session for a given server */
	if((status = OCISessionBegin( 
		m_svchp, m_errhp, m_seshp,
		OCI_CRED_RDBMS,
		(ub4)OCI_DEFAULT )) != OCI_SUCCESS)
	{
		_DB_ThrowException(status, m_errhp);
	}
	
	/* set attribute session in the service context */
	if((status = OCIAttrSet( 
		(dvoid*)m_svchp,
		(ub4) OCI_HTYPE_SVCCTX,
		(dvoid*) m_seshp,
		(ub4) 0,
		(ub4) OCI_ATTR_SESSION,
		m_errhp )) != OCI_SUCCESS)
	{
		_DB_ThrowException(status, m_errhp);
	}
	
	/* allocates sql statement handle */
	if((status = OCIHandleAlloc( (dvoid*) m_envhp,
		(dvoid**) &m_stmhp,
		(ub4) OCI_HTYPE_STMT,
		(size_t) 0,
		(dvoid**) 0 )) != OCI_SUCCESS)
	{
		_DB_ThrowException(status, m_envhp);
	}
	
	/* allocates sql statement handle for cursor */
	if((status = OCIHandleAlloc( (dvoid*) m_envhp,
		(dvoid**) &m_cursor,
		(ub4) OCI_HTYPE_STMT,
		(size_t) 0,
		(dvoid**) 0 )) != OCI_SUCCESS)
	{
		_DB_ThrowException(status, m_envhp);
	}
	
	m_bConnected = TRUE;	//gary0210
	
	/* successful */
	return DB_SUCCESS;
}

/* Called to terminate a user session, detach from a server, and 
delete the enviornment handle */
//gary0210
int CDatabase_::Close()
{
	int status;
	if((status = Cleanup()) != OCI_SUCCESS)
	{
		_DB_ThrowException(DB_FAIL_CLOSE_SESSION,
			"Fail to close database session");
	}
	
	/* successful */
	return DB_SUCCESS;
}


//gary0210
int  CDatabase_::Cleanup()
{
	int status;
	
	m_bConnected = FALSE;
	
	/* terminates a user session context created by OCISessionBegin() */
	if(m_svchp && m_errhp && m_seshp)
		OCISessionEnd( m_svchp, m_errhp, 
		m_seshp, (ub4) OCI_DEFAULT );
	
	/* detach from a server, uninitialize server context handle */
	if(m_srvhp && m_errhp)
		OCIServerDetach( m_srvhp, m_errhp,
		(ub4) OCI_DEFAULT );
	
	/* which deallocates all other handles associated with it */
	if(m_cursor)
	{
		OCIHandleFree((dvoid*)m_cursor,OCI_HTYPE_STMT);
		m_cursor = NULL;
	}
	if(m_stmhp)
	{
		OCIHandleFree((dvoid*)m_stmhp,OCI_HTYPE_STMT);
		m_stmhp = NULL;
	}
	if(m_seshp)
	{
		OCIHandleFree((dvoid*)m_seshp,OCI_HTYPE_SESSION);
		m_seshp = NULL;
	}
	if(m_svchp)
	{
		OCIHandleFree((dvoid*)m_svchp,OCI_HTYPE_SVCCTX);
		m_svchp = NULL;
	}
	if(m_srvhp)
	{
		OCIHandleFree((dvoid*)m_srvhp,OCI_HTYPE_SERVER);
		m_srvhp = NULL;
	}
	//gary0420
	/*m_envhp = (OCIEnv*)		0;
	m_errhp = (OCIError*)	0;
	m_seshp = (OCISession*)	0;
	m_srvhp = (OCIServer*)	0;
	m_svchp = (OCISvcCtx*)	0;
	m_stmhp = (OCIStmt*)	0;*/

	////////////////Add for Statment Binding/////////////
	if(m_pDBPreStmt)
	{
		delete m_pDBPreStmt;
		m_pDBPreStmt = NULL;
	}
	
	memset(m_dbserver, 0, _MAX_DBLENGTH);
	memset(m_database,0, _MAX_DBLENGTH);
	memset(m_username,0, _MAX_DBLENGTH);
	memset(m_password,0, _MAX_DBLENGTH);
	memset(m_sqlstmt,0, _MAX_SQLLENGTH);
	/* successful */
	return DB_SUCCESS;
}

//gary0317
//WARNING:	one string parameter can't include substring as ', or '  ,
void CDatabase_::ParseSQLStatement()
{
	register int    i, iLen;
	char    tmpStmt[_MAX_SQLLENGTH], *p1, *p2, *pBegin, *pEnd;
	BOOL    bLeft = FALSE, bQuate = FALSE, bDouble = FALSE;
	
	memset(tmpStmt, 0, _MAX_SQLLENGTH);
	p2 = tmpStmt;
	pBegin = (char*)m_sqlstmt;
	
	while((pEnd = strchr(pBegin, '\'')) != NULL) {
		if(*(pEnd+1) == '\'') {
			if(bDouble) {
				i=1;
				while(*(pEnd+1+i) == ' ') i++;
				if(*(pEnd+1+i) != ',' && *(pEnd+1+i) != ')')
					iLen = pEnd - pBegin +2;
				else {
					iLen = pEnd - pBegin +1;
					bLeft = TRUE;
					bDouble = TRUE;
					bQuate = TRUE;
				}
			}
			else {
				iLen = pEnd - pBegin +1;
				bLeft = TRUE;
				bDouble = TRUE;
			}
		}
		else {
			i=1;
			iLen = pEnd - pBegin +1;
			if(!bLeft) {
				bLeft = TRUE;
				bDouble = TRUE;
				/*
				while(*(pEnd+i) == ' ') i++;
				if(*(pEnd+i) == ',' || *(pEnd+i) == ')') {
				bLeft = FALSE;
				i=1;
				while(*(p1+i) != '\'' && *(p1+i) != '\0') i++;
				if(*(p1+i) == '\'') {
				strncpy(p1+i+1, p1+i, p2-p1-i);
				*(p1+i) = '\'';
				p2 ++;
				}
				}
				*/
			}
			else {
				bLeft = FALSE;
				bDouble = FALSE;
				while(*(pEnd+i) == ' ') i++;
				if(*(pEnd+i) != ',' && *(pEnd+i) != ')') {
					bLeft = TRUE;
					bDouble = TRUE;
					bQuate = TRUE;
				}
			}
		}
		
		p1 = p2;
		strncpy(p2, pBegin, iLen);
		p2 += iLen;
		pBegin += iLen;
		
		if(bQuate) {
			*p2++ = '\'';
			bQuate = FALSE;
		}
	}
	
	strncpy(p2, pBegin, strlen(pBegin));
	
	strcpy((char*)m_sqlstmt, tmpStmt);
}


/* Called to execute PL/SQL block (including stored procedure) directly */
int  CDatabase_::ExecuteSQLDirect(LPCSTR sql_stmt, CRecordset_ *pResultset,
								  short sType )
{
	//TRC_FUNC("CDatabase_::ExecuteSQLDirect...Entered");
	int   status;
	
	if(sql_stmt)
		strcpy((LPSTR)m_sqlstmt, sql_stmt);
	
	if(sType & (IS_PROCEDURE | IS_FUNCTION))	//20000515 for community-SearchUser
		ParseSQLStatement();	//gary0317
	
	if(sType & IS_CURSOR)
	{
		//gary0319
		//pdesc = strchr((char*)m_sqlstmt, ')');
		//if(pdesc != NULL)
		//	*pdesc = 0;
		for(int i=strlen((LPSTR)m_sqlstmt)-1; i>=0; i--)
		{
			if(m_sqlstmt[i] == ')')
			{
				int j=i-1;
				while(m_sqlstmt[j] == ' ' && j>0) j--;
				if(m_sqlstmt[j] != '(')
					m_sqlstmt[i++] = ',';
				m_sqlstmt[i] = '\0';
				break;
			}
		}
		
		sprintf((char*)m_sqlstmt, "%s %s%c", 
			(char*)m_sqlstmt, (char*)P_CURSOR, ')');
	}
	
	if(sType & IS_FUNCTION)
	{
		text sqlstmt[_MAX_SQLLENGTH];
		strcpy((char*)sqlstmt, (char*)m_sqlstmt);
		sprintf((char*)m_sqlstmt, "%s %s %s",
			(char*)P_RETURN, ":=", sqlstmt);
	}
	
	if(sType & (IS_PROCEDURE | IS_FUNCTION))
	{
		text sqlstmt[_MAX_SQLLENGTH];
		strcpy((char*)sqlstmt, (char*)m_sqlstmt);
		sprintf((char*)m_sqlstmt, "%s %s%c %s", 
			"BEGIN", 
			(char*)sqlstmt,
			';',
			"END;" );
	}
	
	//TRC_INFO((char*)m_sqlstmt);
	/* stored procedure or function */
	if(sType & (IS_PROCEDURE | IS_FUNCTION)) 
	{
		if(pResultset == NULL)
		{
			OCIBind  *bndhp  = (OCIBind*)   0;
			OCIBind  *bndhp2 = (OCIBind*)   0;
			
			//TRC_INFO("OCIStmtPrepare Start");
			/* prepare PL/SQL statement */
			if((status = OCIStmtPrepare( m_stmhp,
				m_errhp,
				(text*) m_sqlstmt,
				(ub4) strlen((char*)m_sqlstmt),
				(ub4) OCI_NTV_SYNTAX,
				(ub4) OCI_DEFAULT )) != OCI_SUCCESS)
			{
				//pResultset->Cleanup();
				_DB_ThrowException(status, m_errhp);
				//return status;
			}
			//TRC_INFO("OCIStmtPrepare End");
			
			/* bind cursor by Name */
			if(sType & IS_CURSOR)	//gary0207
				if((status = OCIBindByName( m_stmhp,
					& bndhp,
					m_errhp,
					(text*) P_CURSOR,
					-1,
					(dvoid*) &m_cursor,
					0,
					SQLT_RSET,
					0, 
					0, 0, 0, 0,
					OCI_DEFAULT )) != OCI_SUCCESS)
				{
					//pResultset->Cleanup();
					_DB_ThrowException(status, m_errhp);
					//return status;
				}
				
				
				/* bind return value by Name */
				if(sType & IS_FUNCTION)
					if((status = OCIBindByName( m_stmhp,
						& bndhp2,
						m_errhp,
						(text*) P_RETURN,
						strlen(P_RETURN),
						& m_iRet,
						sizeof(int),
						SQLT_INT,
						0,
						0, 0, 0, 0,
						OCI_DEFAULT )) != OCI_SUCCESS)
					{
						//pResultset->Cleanup();
						_DB_ThrowException(status, m_errhp);
						//return status;
					}
					
					//TRC_INFO("OCIStmtExecute Start");
					/* execute PL/SQL statement */
					if((status = OCIStmtExecute( m_svchp, 
						m_stmhp, 
						m_errhp,
						(ub4) 1,	/* iteration=1 controls how many times the
						statement is executed during array operations*/
						(ub4) 0,
						(OCISnapshot*) NULL,
						(OCISnapshot*) NULL,
						OCI_COMMIT_ON_SUCCESS )) != OCI_SUCCESS)
					{
						//pResultset->Cleanup();
						_DB_ThrowException(status, m_errhp);
						//return status;
					}
					//TRC_INFO("OCIStmtExecute End");
		}
		else	//pResultset != NULL
		{
			if((status = pResultset->FillResultSet(sType)) != OCI_SUCCESS)
			{
				// gary Jan.11 2000
				if( status != OCI_NO_DATA && 
					status != OCI_SUCCESS_WITH_INFO)
				{
					pResultset->CleanupA();
					pResultset->Cleanup();	//gary0208
					_DB_ThrowException(status, m_errhp);
					//return status;
				}
			}
		}
	}
	else	/* one sql statement */
	{
		if(pResultset == NULL)
		{
			/* prepare PL/SQL statement */
			if((status = OCIStmtPrepare( m_stmhp, 
				m_errhp,
				(text*) m_sqlstmt,
				(ub4) strlen((char*)m_sqlstmt),
				(ub4) OCI_NTV_SYNTAX,
				(ub4) OCI_DEFAULT )) != OCI_SUCCESS)
			{
				_DB_ThrowException(status, m_errhp);
				//return status;
			}
			
			/* execute PL/SQL statement */
			if((status = OCIStmtExecute( m_svchp, 
				m_stmhp, 
				m_errhp,
				(ub4) 1,
				(ub4) 0,
				(OCISnapshot*) NULL,
				(OCISnapshot*) NULL,
				//OCI_DEFAULT ))
				OCI_COMMIT_ON_SUCCESS )) != OCI_SUCCESS)
			{
				
				_DB_ThrowException(status, m_errhp);
				//return status;
			}
		}
		else	//pResultset != NULL
		{
			if((status = pResultset->FillResultSet(sType)) != OCI_SUCCESS)
			{
				// gary Jan.11 2000
				if(status != OCI_NO_DATA && 
					status != OCI_SUCCESS_WITH_INFO)
				{
					pResultset->CleanupA();
					pResultset->Cleanup();	//gary0208
					_DB_ThrowException(status, m_errhp);
					//return status;
				}
			}
		}
	}
	
	// TRC_FUNC("CDatabase_::ExecuteSQLDirect...Returned");
	
	/* successful */
	return DB_SUCCESS;
}


/* called to get a value from CVariant_ */
// 000515	if "NULL" value, just assign to "0", don't throw
int  CDatabase_::GetItemValueA(CVariant_ *pItem, LPBYTE pVal, int dty)
{
	int status;
	int iVal;
	
	switch(dty)
	{
	case DTY_DWORD:
		switch(pItem->m_nType)
		{
		case SQLT_NUM:
			if((status = OCINumberToInt(
				m_errhp,
				(OCINumber*) &pItem->m_number,
				(uword) sizeof(DWORD),
				(uword) OCI_NUMBER_UNSIGNED,
				(dvoid*) pVal )) != OCI_SUCCESS)
			{
				*(DWORD*)pVal = 0;
				//_DB_ThrowException(status, m_errhp);
			}
			break;
		case SQLT_INT:
			*(DWORD*)pVal = (DWORD)pItem->m_iVal;
			break;
		case SQLT_UIN:
			*(DWORD*)pVal = (DWORD)pItem->m_uiVal;
			break;
		case SQLT_FLT:
			*(DWORD*)pVal = (DWORD)pItem->m_fltVal;
			break;
		default:
			_DB_ThrowException(DB_FAIL_INVALID_DATATYPE,
				"Fail to get item value for invalid data type");
			break;
		}
		break;
		case DTY_WORD:
			switch(pItem->m_nType)
			{
			case SQLT_NUM:
				if((status = OCINumberToInt(m_errhp,
					(OCINumber*) &pItem->m_number,
					(uword) sizeof(WORD),
					(uword) OCI_NUMBER_UNSIGNED,
					(dvoid*) pVal )) != OCI_SUCCESS)
				{
					*(WORD*)pVal = 0;
					//_DB_ThrowException(status, m_errhp);
				}
				break;
			case SQLT_INT:
				*(WORD*)pVal = (WORD)pItem->m_iVal;
				break;
			case SQLT_UIN:
				*(WORD*)pVal = (WORD)pItem->m_uiVal;
				break;
			case SQLT_FLT:
				*(WORD*)pVal = (WORD)pItem->m_fltVal;
				break;
			default:
				_DB_ThrowException(DB_FAIL_INVALID_DATATYPE,
					"Fail to get item value for invalid data type");
				break;
			}
			break;
			case DTY_BYTE:
				switch(pItem->m_nType)
				{
				case SQLT_NUM:
					if((status = OCINumberToInt(
						m_errhp,
						(OCINumber*) &pItem->m_number,
						(uword) sizeof(int),
						(uword) OCI_NUMBER_SIGNED,
						(dvoid*) &iVal )) != OCI_SUCCESS)
					{
						*(BYTE*)pVal = 0;
						//_DB_ThrowException(status, m_errhp);
					}
					else
						*(BYTE*)pVal = (BYTE)iVal;
					break;
				case SQLT_INT:
					*(BYTE*)pVal = (BYTE)pItem->m_iVal;
					break;
				case SQLT_UIN:
					*(BYTE*)pVal = (BYTE)pItem->m_uiVal;
					break;
				case SQLT_FLT:
					*(BYTE*)pVal = (BYTE)pItem->m_fltVal;
					break;
				default:
					_DB_ThrowException(DB_FAIL_INVALID_DATATYPE,
						"Fail to get item value for invalid data type");
					break;
				}
				break;
				case DTY_BOOL:
					switch(pItem->m_nType)
					{
					case SQLT_NUM:
						if((status = OCINumberToInt(m_errhp,
							(OCINumber*) &pItem->m_number,
							(uword) sizeof(int),
							(uword) OCI_NUMBER_SIGNED,
							(dvoid*) &iVal )) != OCI_SUCCESS)	//gary0209
						{
							*(BOOL*)pVal = 0;
							//_DB_ThrowException(status, m_errhp);
						}
						else
							*(BOOL*)pVal = (BOOL)iVal;
						break;
					case SQLT_INT:
						*(BOOL*)pVal = (BOOL)pItem->m_iVal;
						break;
					case SQLT_UIN:
						*(BOOL*)pVal = (BOOL)pItem->m_uiVal;
						break;
					case SQLT_FLT:
						*(BOOL*)pVal = (BOOL)pItem->m_fltVal;
						break;
					default:
						_DB_ThrowException(DB_FAIL_INVALID_DATATYPE,
							"Fail to get item value for invalid data type");
						break;
					}
					break;
					case DTY_LONG:
						switch(pItem->m_nType)
						{
						case SQLT_NUM:
							if((status = OCINumberToInt(m_errhp,
								(OCINumber*) &pItem->m_number,
								(uword) sizeof(long),
								(uword) OCI_NUMBER_SIGNED,
								(dvoid*) pVal )) != OCI_SUCCESS)
							{
								*(long*)pVal = 0;
								//_DB_ThrowException(status, m_errhp);
							}
							break;
						case SQLT_INT:
							*(long*)pVal = (long)pItem->m_iVal;
							break;
						case SQLT_UIN:
							*(long*)pVal = (long)pItem->m_uiVal;
							break;
						case SQLT_FLT:
							*(long*)pVal = (long)pItem->m_fltVal;
							break;
						default:
							_DB_ThrowException(DB_FAIL_INVALID_DATATYPE,
								"Fail to get item value for invalid data type");
							break;
						}
						break;
						case DTY_SHORT:
							switch(pItem->m_nType)
							{
							case SQLT_NUM:
								if((status = OCINumberToInt(m_errhp,
									(OCINumber*) &pItem->m_number,
									(uword) sizeof(short),
									(uword) OCI_NUMBER_SIGNED,
									(dvoid*) pVal )) != OCI_SUCCESS)
								{
									*(short*)pVal = 0;
									//_DB_ThrowException(status, m_errhp);
								}
								break;
							case SQLT_INT:
								*(short*)pVal = (short)pItem->m_iVal;
								break;
							case SQLT_UIN:
								*(short*)pVal = (short)pItem->m_uiVal;
								break;
							case SQLT_FLT:
								*(short*)pVal = (short)pItem->m_fltVal;
								break;
							default:
								_DB_ThrowException(DB_FAIL_INVALID_DATATYPE,
									"Fail to get item value for invalid data type");
								break;
							}
							break;
							case DTY_FLOAT:
								switch(pItem->m_nType)
								{
								case SQLT_NUM:
									if((status = OCINumberToReal(m_errhp,
										(OCINumber*) &pItem->m_number,
										(uword) sizeof(float),
										(dvoid*) pVal )) != OCI_SUCCESS)
									{
										*(float*)pVal = 0;
										//_DB_ThrowException(status, m_errhp);
									}
									break;
								case SQLT_INT:
									*(float*)pVal = (float)pItem->m_iVal;
									break;
								case SQLT_UIN:
									*(float*)pVal = (float)pItem->m_uiVal;
									break;
								case SQLT_FLT:
									*(float*)pVal = (float)pItem->m_fltVal;
									break;
								default:
									_DB_ThrowException(DB_FAIL_INVALID_DATATYPE,
										"Fail to get item value for invalid data type");
									break;
								}
								break;
								case DTY_DOUBLE:
									switch(pItem->m_nType)
									{
									case SQLT_NUM:
										if((status = OCINumberToReal(m_errhp,
											(OCINumber*) &pItem->m_number,
											(uword) sizeof(double),
											(dvoid*) pVal )) != OCI_SUCCESS)
										{
											*(double*)pVal = 0;
											//_DB_ThrowException(status, m_errhp);
										}
										break;
									case SQLT_INT:
										*(double*)pVal = (double)pItem->m_iVal;
										break;
									case SQLT_UIN:
										*(double*)pVal = (double)pItem->m_uiVal;
										break;
									case SQLT_FLT:
										*(double*)pVal = (double)pItem->m_fltVal;
										break;
									default:
										_DB_ThrowException(DB_FAIL_INVALID_DATATYPE,
											"Fail to get item value for invalid data type");
										break;
									}
									break;
									case DTY_STRING:
										if(pItem->m_nType == SQLT_CHR)
											strcpy((char*)pVal, pItem->m_pString);
										else
											_DB_ThrowException(DB_FAIL_INVALID_DATATYPE,
											"Fail to get item value for invalid data type");
										break;
									case DTY_NUMBER:
										if(pItem->m_nType == SQLT_NUM)
											*(OCINumber*)pVal = pItem->m_number;
										else
											_DB_ThrowException(DB_FAIL_INVALID_DATATYPE,
											"Fail to get item value for invalid data type");
										break;
									case DTY_TIME:
										if(pItem->m_nType == SQLT_DAT)
											memcpy(pVal, &pItem->m_time, sizeof(OCIDate));
										else
											_DB_ThrowException(DB_FAIL_INVALID_DATATYPE,
											"Fail to get item value for invalid data type");
										break;
									case DTY_BINARY:
										if(pItem->m_nType == SQLT_BIN)
											pVal = (LPBYTE)pItem->m_pBinary;
										else
											_DB_ThrowException(DB_FAIL_INVALID_DATATYPE,
											"Fail to get item value for invalid data type");
										break;
									case DTY_PDN:
										break;
									default:
										_DB_ThrowException(DB_FAIL_INVALID_DATATYPE,
											"Fail to get item value for invalid data type");
										break;
	}
	
	return DB_SUCCESS;
}

/* called to get a value from CVariant_ */
/* try... catch...						*/
int  CDatabase_::GetItemValue(CVariant_ *pItem, LPBYTE pVal, int dty)
{
	int status;
	int iVal;	//gary0209
	
	switch(dty)
	{
	case DTY_DWORD:
		switch(pItem->m_nType)
		{
		case SQLT_NUM:
			if((status = OCINumberToInt(m_errhp,
				(OCINumber*) &pItem->m_number,
				(uword) sizeof(DWORD),
				(uword) OCI_NUMBER_UNSIGNED,
				(dvoid*) pVal )) != OCI_SUCCESS)
			{
				*(DWORD*)pVal = 0;
				_DB_ThrowException(status, m_errhp);
			}
			break;
		case SQLT_INT:
			*(DWORD*)pVal = (DWORD)pItem->m_iVal;
			break;
		case SQLT_UIN:
			*(DWORD*)pVal = (DWORD)pItem->m_uiVal;
			break;
		case SQLT_FLT:
			*(DWORD*)pVal = (DWORD)pItem->m_fltVal;
			break;
		default:
			_DB_ThrowException(DB_FAIL_INVALID_DATATYPE,
				"Fail to get item value for invalid data type");
			break;
		}
		break;
		case DTY_WORD:
			switch(pItem->m_nType)
			{
			case SQLT_NUM:
				if((status = OCINumberToInt(m_errhp,
					(OCINumber*) &pItem->m_number,
					(uword) sizeof(WORD),
					(uword) OCI_NUMBER_UNSIGNED,
					(dvoid*) pVal )) != OCI_SUCCESS)
				{
					*(WORD*)pVal = 0;
					_DB_ThrowException(status, m_errhp);
				}
				break;
			case SQLT_INT:
				*(WORD*)pVal = (WORD)pItem->m_iVal;
				break;
			case SQLT_UIN:
				*(WORD*)pVal = (WORD)pItem->m_uiVal;
				break;
			case SQLT_FLT:
				*(WORD*)pVal = (WORD)pItem->m_fltVal;
				break;
			default:
				_DB_ThrowException(DB_FAIL_INVALID_DATATYPE,
					"Fail to get item value for invalid data type");
				break;
			}
			break;
			case DTY_BYTE:
				switch(pItem->m_nType)
				{
				case SQLT_NUM:
					if((status = OCINumberToInt(m_errhp,
						(OCINumber*) &pItem->m_number,
						(uword) sizeof(BYTE),
						(uword) OCI_NUMBER_UNSIGNED,
						(dvoid*) pVal )) != OCI_SUCCESS)
					{
						*(BYTE*)pVal = 0;
						_DB_ThrowException(status, m_errhp);
					}
					break;
				case SQLT_INT:
					*(BYTE*)pVal = (BYTE)pItem->m_iVal;
					break;
				case SQLT_UIN:
					*(BYTE*)pVal = (BYTE)pItem->m_uiVal;
					break;
				case SQLT_FLT:
					*(BYTE*)pVal = (BYTE)pItem->m_fltVal;
					break;
				default:
					_DB_ThrowException(DB_FAIL_INVALID_DATATYPE,
						"Fail to get item value for invalid data type");
					break;
				}
				break;
				case DTY_BOOL:
					switch(pItem->m_nType)
					{
					case SQLT_NUM:
						if((status = OCINumberToInt(m_errhp,
							(OCINumber*) &pItem->m_number,
							(uword) sizeof(int),
							(uword) OCI_NUMBER_SIGNED,
							(dvoid*) &iVal )) != OCI_SUCCESS)	//gary0209
						{
							*(BOOL*)pVal = 0;
							_DB_ThrowException(status, m_errhp);
						}
						*(BOOL*)pVal = (BOOL)iVal;
						break;
					case SQLT_INT:
						*(BOOL*)pVal = (BOOL)pItem->m_iVal;
						break;
					case SQLT_UIN:
						*(BOOL*)pVal = (BOOL)pItem->m_uiVal;
						break;
					case SQLT_FLT:
						*(BOOL*)pVal = (BOOL)pItem->m_fltVal;
						break;
					default:
						_DB_ThrowException(DB_FAIL_INVALID_DATATYPE,
							"Fail to get item value for invalid data type");
						break;
					}
					break;
					case DTY_LONG:
						switch(pItem->m_nType)
						{
						case SQLT_NUM:
							if((status = OCINumberToInt(m_errhp,
								(OCINumber*) &pItem->m_number,
								(uword) sizeof(long),
								(uword) OCI_NUMBER_SIGNED,
								(dvoid*) pVal )) != OCI_SUCCESS)
							{
								*(long*)pVal = 0;
								_DB_ThrowException(status, m_errhp);
							}
							break;
						case SQLT_INT:
							*(long*)pVal = (long)pItem->m_iVal;
							break;
						case SQLT_UIN:
							*(long*)pVal = (long)pItem->m_uiVal;
							break;
						case SQLT_FLT:
							*(long*)pVal = (long)pItem->m_fltVal;
							break;
						default:
							_DB_ThrowException(DB_FAIL_INVALID_DATATYPE,
								"Fail to get item value for invalid data type");
							break;
						}
						break;
						case DTY_SHORT:
							switch(pItem->m_nType)
							{
							case SQLT_NUM:
								if((status = OCINumberToInt(m_errhp,
									(OCINumber*) &pItem->m_number,
									(uword) sizeof(short),
									(uword) OCI_NUMBER_SIGNED,
									(dvoid*) pVal )) != OCI_SUCCESS)
								{
									*(short*)pVal = 0;
									_DB_ThrowException(status, m_errhp);
								}
								break;
							case SQLT_INT:
								*(short*)pVal = (short)pItem->m_iVal;
								break;
							case SQLT_UIN:
								*(short*)pVal = (short)pItem->m_uiVal;
								break;
							case SQLT_FLT:
								*(short*)pVal = (short)pItem->m_fltVal;
								break;
							default:
								_DB_ThrowException(DB_FAIL_INVALID_DATATYPE,
									"Fail to get item value for invalid data type");
								break;
							}
							break;
							case DTY_FLOAT:
								switch(pItem->m_nType)
								{
								case SQLT_NUM:
									if((status = OCINumberToReal(m_errhp,
										(OCINumber*) &pItem->m_number,
										(uword) sizeof(float),
										(dvoid*) pVal )) != OCI_SUCCESS)
									{
										*(float*)pVal = 0;
										_DB_ThrowException(status, m_errhp);
									}
									break;
								case SQLT_INT:
									*(float*)pVal = (float)pItem->m_iVal;
									break;
								case SQLT_UIN:
									*(float*)pVal = (float)pItem->m_uiVal;
									break;
								case SQLT_FLT:
									*(float*)pVal = (float)pItem->m_fltVal;
									break;
								default:
									_DB_ThrowException(DB_FAIL_INVALID_DATATYPE,
										"Fail to get item value for invalid data type");
									break;
								}
								break;
								case DTY_DOUBLE:
									switch(pItem->m_nType)
									{
									case SQLT_NUM:
										if((status = OCINumberToReal(m_errhp,
											(OCINumber*) &pItem->m_number,
											(uword) sizeof(double),
											(dvoid*) pVal )) != OCI_SUCCESS)
										{
											*(double*)pVal = 0;
											_DB_ThrowException(status, m_errhp);
										}
										break;
									case SQLT_INT:
										*(double*)pVal = (double)pItem->m_iVal;
										break;
									case SQLT_UIN:
										*(double*)pVal = (double)pItem->m_uiVal;
										break;
									case SQLT_FLT:
										*(double*)pVal = (double)pItem->m_fltVal;
										break;
									default:
										_DB_ThrowException(DB_FAIL_INVALID_DATATYPE,
											"Fail to get item value for invalid data type");
										break;
									}
									break;
									case DTY_STRING:
										if(pItem->m_nType == SQLT_CHR)
											strcpy((char*)pVal, pItem->m_pString);
										else
											_DB_ThrowException(DB_FAIL_INVALID_DATATYPE,
											"Fail to get item value for invalid data type");
										break;
									case DTY_NUMBER:
										if(pItem->m_nType == SQLT_NUM)
											*(OCINumber*)pVal = pItem->m_number;
										else
											_DB_ThrowException(DB_FAIL_INVALID_DATATYPE,
											"Fail to get item value for invalid data type");
										break;
									case DTY_TIME:
										if(pItem->m_nType == SQLT_DAT)
											memcpy(pVal, &pItem->m_time, sizeof(OCIDate));
										else
											_DB_ThrowException(DB_FAIL_INVALID_DATATYPE,
											"Fail to get item value for invalid data type");
										break;
									case DTY_BINARY:
										if(pItem->m_nType == SQLT_BIN)
											pVal = (LPBYTE)pItem->m_pBinary;
										else
											_DB_ThrowException(DB_FAIL_INVALID_DATATYPE,
											"Fail to get item value for invalid data type");
										break;
									case DTY_PDN:
										break;
									default:
										_DB_ThrowException(DB_FAIL_INVALID_DATATYPE,
											"Fail to get item value for invalid data type");
										break;
	}
	
	return DB_SUCCESS;
}


int CDatabase_::GetIntFromOCINumber(OCINumber* pnumber, LPBYTE pVal)
{
	BOOL	ret;
	int		status;
	if((status = OCINumberIsInt(m_errhp,	pnumber, &ret)) != OCI_SUCCESS)
	{
		*(int*)pVal = 0;
		return status;
	}
	status = ret ? 0 : -1;
	if(ret && (status = OCINumberToInt(m_errhp, 
								pnumber,
								(uword) sizeof(int), 
								(uword) OCI_NUMBER_SIGNED, 
								(dvoid*) pVal )))
	{
		*(int*)pVal = 0;
		_DB_ThrowException(status, m_errhp);
		//return status;
	}
	
	return DB_SUCCESS;
}

int CDatabase_::GetUIntFromOCINumber(OCINumber* pnumber, LPBYTE pVal)
{
	BOOL	ret;
	int		status;
	if((status = OCINumberIsInt(m_errhp,	pnumber, &ret)) != OCI_SUCCESS)
	{
		*(int*)pVal = 0;
		return status;
	}
	status = ret ? 0 : -1;
	if(ret && (status = OCINumberToInt(m_errhp, 
								pnumber,
								(uword) sizeof(int), 
								(uword) OCI_NUMBER_UNSIGNED, 
								(dvoid*) pVal )))
	{
		*(int*)pVal = 0;
		_DB_ThrowException(status, m_errhp);
		//return status;
	}
	
	return DB_SUCCESS;
}

int CDatabase_::GetRealFromOCINumber(OCINumber* pnumber, LPBYTE pVal)
{
	BOOL	ret;
	int		status;
	if((status = OCINumberIsInt(m_errhp, pnumber, &ret)) != OCI_SUCCESS)
	{
		*(double*)pVal = 0;
		_DB_ThrowException(status, m_errhp);
		//return status;
	}
	
	status = ret ? -1 : 0;
	
	if(ret == 1) //the OCINumber is Int
	{
		int nTmpVal = 0; 
		if(ret && (status = OCINumberToInt(m_errhp, 
			pnumber,
			(uword) sizeof(int), 
			(uword) OCI_NUMBER_UNSIGNED, 
			(dvoid*) &nTmpVal )))
		{
			*(double*)pVal = 0;
			_DB_ThrowException(status, m_errhp);
		}
		*(reinterpret_cast<double*>(pVal)) = nTmpVal;
	}
	else
	{
		if(!ret && (status = OCINumberToReal(m_errhp, 
			pnumber,
			(uword) sizeof(double), 
			(dvoid*) pVal )))
		{
			*(double*)pVal = 0;
			_DB_ThrowException(status, m_errhp);
		}
	}
	
	return DB_SUCCESS;
}

int	 CDatabase_::GetGMTTimeFromOCIDate(OCIDate*  ptime, gmt_time*  tm)
{
	int		valid;
	int		status;
	
	memset(tm, 0, sizeof(gmt_time));
	
	if((status = OCIDateCheck(m_errhp, ptime, (uword*)&valid)) != OCI_SUCCESS)
	{
		_DB_ThrowException(status, m_errhp);
	}
	
	if(valid)	return valid;
	
	sb2		year;
	ub1		month, day, hour, minute, second;
	OCIDateGetDate(ptime, (sb2*) &year, (ub1*) &month, (ub1*) &day);
	OCIDateGetTime(ptime, (ub1*) &hour, (ub1*) &minute,(ub1*) &second);
	
	tm->wYear		= (WORD) year;
	tm->wMonth		= (WORD) month;
	tm->wDay		= (WORD) day;
	tm->wHour		= (WORD) hour;
	tm->wMinute		= (WORD) minute;
	tm->wSecond		= (WORD) second;
	tm->wReserved	= (WORD) 0;
	
	return DB_SUCCESS;
}

////////////////////////////////Add for Statment Binding//////////////////////////
int CDatabase_::PrepareSQLStmt(LPCSTR pszSQLStmt)
{
	if(pszSQLStmt == NULL)
		return -1;
	
	sword status;
	if((status = OCIStmtPrepare( m_stmhp, 
		m_errhp,
		(text*) pszSQLStmt,
		(ub4) strlen((char*)pszSQLStmt),
		(ub4) OCI_NTV_SYNTAX,
		(ub4) OCI_DEFAULT )) != OCI_SUCCESS)
	{
		_DB_ThrowException(status, m_errhp);
	}
	
	if(m_pDBPreStmt == NULL)	
		m_pDBPreStmt = new CDBPreStmt_(this, pszSQLStmt);
	
	return DB_SUCCESS;	
}

int CDatabase_::BindInParamByName(LPCSTR pszParamName, DWORD &dwContent)
{
	try
	{
		RT_ASSERTE(m_pDBPreStmt);
		m_pDBPreStmt->BindInParamByName(pszParamName, dwContent);
	}
	catch(CDBException_ e)
	{
		if(m_pDBPreStmt)
		{
			delete m_pDBPreStmt;
			m_pDBPreStmt = NULL;
		}
		
		throw(e);
	}
	
	return DB_SUCCESS;
}

int CDatabase_::BindInParamByName(LPCSTR pszParamName, LPBYTE pszContent)
{
	try
	{
		RT_ASSERTE(m_pDBPreStmt);
		m_pDBPreStmt->BindInParamByName(pszParamName, pszContent);
	}
	catch(CDBException_ e)
	{
		if(m_pDBPreStmt)
		{
			delete m_pDBPreStmt;
			m_pDBPreStmt = NULL;
		}
		
		throw(e);
	}
	
	return DB_SUCCESS;
}

int CDatabase_::ExecutePreparedSQLStmt()
{
	sword status;
	
	//Do a insert job
	if((status = OCIStmtExecute( m_svchp, 
		m_stmhp, 
		m_errhp,
		(ub4) 1,	//iter = 1(Insert), or iter = 0(select)
		(ub4) 0,
		(OCISnapshot*) NULL,
		(OCISnapshot*) NULL,
		OCI_COMMIT_ON_SUCCESS )) != OCI_SUCCESS)
	{
		if(m_pDBPreStmt)
		{
			delete m_pDBPreStmt;
			m_pDBPreStmt = NULL;
		}
		
		_DB_ThrowException(status, m_errhp);
	}
	
	if(m_pDBPreStmt)
	{
		delete m_pDBPreStmt;
		m_pDBPreStmt = NULL;
	}
	
	return DB_SUCCESS;
}

int CDatabase_::BindOutParamByName(LPCSTR pszParamName, DWORD &dwContent)
{
	try
	{
		m_pDBPreStmt->BindOutParamByName(pszParamName, dwContent);
	}
	catch(CDBException_ e)
	{
		if(m_pDBPreStmt)
		{
			delete m_pDBPreStmt;
			m_pDBPreStmt = NULL;
		}
		
		throw(e);
	}
	
	return DB_SUCCESS;
}

int CDatabase_::BindOutParamByName(LPCSTR pszParamName, LPBYTE pszContent)
{
	try
	{
		m_pDBPreStmt->BindOutParamByName(pszParamName, pszContent);
	}
	catch(CDBException_ e)
	{
		if(m_pDBPreStmt)
		{
			delete m_pDBPreStmt;
			m_pDBPreStmt = NULL;
		}
		
		throw(e);
	}
	
	return DB_SUCCESS;
}
/*--------------------------------------------------------------*/
/*																*/
/* 	class CRecordset_ 											*/
/*																*/
/*--------------------------------------------------------------*/
CRecordset_::CRecordset_(CDatabase_ *pDatabase):m_pDatabase(pDatabase)
{
	int i;
	for(i=0; i<_MAX_PARAMETERS; i++)
		m_bndhp[i] = (OCIBind*) 0;
	for(i=0; i<_MAX_PARAMETERS; i++)
		m_defhp[i] = (OCIDefine*) 0;
	for(i=0; i<_MAX_PARAMETERS; i++)
		bnd_indp[i] = 0;
	for(i=0; i<_MAX_PARAMETERS; i++)
		def_indp[i] = 0;
	
	m_stmhp  = (OCIStmt*) 0;
	m_cursor = (OCIStmt*) 0;
	
	n_Bind   = 0;
	n_Define = 0;
	
	memset((char*)m_sqlstmt, 0, _MAX_SQLLENGTH);
}

CRecordset_::~CRecordset_()
{
	Destroy();
}

int CRecordset_::Destroy()
{
	CleanupA();
	Cleanup();
	return DB_SUCCESS;
}
/* Called to clean up */
int  CRecordset_::CleanupA()
{
	while(m_aColDescriptors.GetCount() > 0)
	{
		CDBColumnDescriptor_ *pColDesc =
			(CDBColumnDescriptor_ *)m_aColDescriptors[0];
		m_aColDescriptors.RemoveAt(0);
		if(pColDesc)
			delete pColDesc;
	}
	
	while(m_aRecords.GetCount() > 0)
	{
		CDBRecord_ *pRec = (CDBRecord_ *)m_aRecords[0];
		m_aRecords.RemoveAt(0);
		if(pRec)
			delete pRec;
	}
	
	return DB_SUCCESS;
}

int  CRecordset_::Cleanup()
{
	/* deallocates sql statement handle */
	if(m_stmhp)
		OCIHandleFree( (dvoid*) m_stmhp, OCI_HTYPE_STMT );
	
	if(m_cursor)
		OCIHandleFree( (dvoid*) m_cursor, OCI_HTYPE_STMT );
	
	int i;
	for(i=0; i<_MAX_PARAMETERS; i++)
		m_bndhp[i] = (OCIBind*) 0;
	for(i=0; i<_MAX_PARAMETERS; i++)
		m_defhp[i] = (OCIDefine*) 0;
	for(i=0; i<_MAX_PARAMETERS; i++)
		bnd_indp[i] = 0;
	for(i=0; i<_MAX_PARAMETERS; i++)
		def_indp[i] = 0;
	
	m_stmhp = (OCIStmt*)  0;
	m_cursor = (OCIStmt*) 0;
	
	n_Bind   = 0;
	n_Define = 0;
	
	memset((char*)m_sqlstmt, 0, _MAX_SQLLENGTH);
	
	return DB_SUCCESS;
}


/* Called to initialize parameters */
int  CRecordset_::Initialize()
{
	RT_ASSERTE(m_pDatabase);
	int status;
	
	if(m_stmhp || m_cursor)
		Cleanup();
	
	if((status = OCIHandleAlloc( (dvoid*)m_pDatabase->m_envhp,
		(dvoid**) &m_stmhp,
		OCI_HTYPE_STMT,
		(size_t) 0,
		(dvoid**) 0 )) != OCI_SUCCESS)
	{
		_DB_ThrowException(status, m_pDatabase->m_envhp);
		//_DB_ThrowException(_OCI_FAIL_ALLOCATE_STATEMENT_HANDLE,
		//"Fail to allocate OCI sql statement handle");
		//return status;
	}
	
	if((status = OCIHandleAlloc( (dvoid*)m_pDatabase->m_envhp,
		(dvoid**) &m_cursor,
		OCI_HTYPE_STMT,
		(size_t) 0,
		(dvoid**) 0 )) != OCI_SUCCESS)
	{
		_DB_ThrowException(status, m_pDatabase->m_envhp);
		//_DB_ThrowException(_OCI_FAIL_ALLOCATE_STATEMENT_HANDLE,
		//"Fail to allocate OCI sql statement handle");
		//return status;
	}
	
	return DB_SUCCESS;
}


/* Called to prepare a sql statement */
int  CRecordset_::PrepareSQL(LPBYTE sql_stmt)
{
	strcpy((char*)m_sqlstmt, (char*)sql_stmt);
	
	int status;
	if((status = OCIStmtPrepare(m_stmhp, m_pDatabase->m_errhp,
		(text*) m_sqlstmt,
		(ub4) strlen((char*)m_sqlstmt),
		(ub4) OCI_NTV_SYNTAX,
		(ub4) OCI_DEFAULT )) != OCI_SUCCESS)
	{
		_DB_ThrowException(status, m_pDatabase->m_errhp);
		//return status;
	}
	
	return DB_SUCCESS;
}


/* Called to create an association between a select-list
variable and an input variable by name */
int  CRecordset_::BindByName(LPBYTE placeholder,
							 dvoid* valuep, int value_size,
							 USHORT datatype,
							 BOOL bIsCursorStmt)
{
	RT_ASSERTE_RETURN(n_Bind < _MAX_PARAMETERS, DB_ERROR);
	int status;
	if((status = OCIBindByName( 
		bIsCursorStmt ? m_cursor : m_stmhp,
		&m_bndhp[n_Bind],
		m_pDatabase->m_errhp,
		(text*) placeholder, -1,
		(dvoid*) valuep, (sb4) value_size,
		(ub2) datatype,
		(dvoid*) &bnd_indp[n_Bind], 
		(ub2*) 0, (ub2*) 0, (ub4) 0, (ub4*) 0,
		OCI_DEFAULT )) != OCI_SUCCESS)
	{
		_DB_ThrowException(status, m_pDatabase->m_errhp);
		//return status;
	}
	
	n_Bind ++;
	
	return DB_SUCCESS;
}

/* Called to create an association between a select-list
variable and an input variable by position */
int  CRecordset_::BindByPos(UINT position,
							dvoid* valuep, int value_size,
							USHORT datatype,
							BOOL bIsCursorStmt)
{
	RT_ASSERTE_RETURN(n_Bind < _MAX_PARAMETERS, DB_ERROR);
	int status;
	if((status = OCIBindByPos( 
		bIsCursorStmt ? m_cursor : m_stmhp,
		&m_bndhp[n_Bind],
		m_pDatabase->m_errhp,
		(ub4) position,
		(dvoid*) valuep, (sb4) value_size,
		(ub2) datatype,
		(dvoid*) &bnd_indp[n_Bind], 
		(ub2*) 0, (ub2*) 0, (ub4) 0, (ub4*) 0,
		OCI_DEFAULT )) != OCI_SUCCESS)
	{
		_DB_ThrowException(status, m_pDatabase->m_errhp);
		//return status;
	}
	
	n_Bind ++;
	
	return DB_SUCCESS;
}



/* Called to create an association between a select-list
variable and a output variable by position */
int  CRecordset_::DefineByPos(UINT position,
							  dvoid* valuep, int value_size,
							  USHORT datatype,
							  BOOL bIsCursorStmt)
{
	RT_ASSERTE_RETURN(n_Define < _MAX_PARAMETERS, DB_ERROR);
	int status;
	if((status = OCIDefineByPos(
		bIsCursorStmt ? m_cursor : m_stmhp,
		&m_defhp[n_Define],
		m_pDatabase->m_errhp,
		(ub4) position,
		(dvoid*) valuep, (sb4) value_size,
		(ub2) datatype,
		(dvoid*) &def_indp[n_Define], 
		(ub2*) 0, (ub2*) 0,
		OCI_DEFAULT )) != OCI_SUCCESS)
	{
		_DB_ThrowException(status, m_pDatabase->m_errhp);
		//return status;
	}
	
	n_Define ++;
	
	return DB_SUCCESS;
}


/* Called to execute a sql statement */
int  CRecordset_::ExecuteSQL(BOOL bDescribeOnly)
{
	int status = 0;	//gary0128
	if(!bDescribeOnly)
	{
		if((status = OCIStmtExecute( m_pDatabase->m_svchp,
			m_stmhp,
			m_pDatabase->m_errhp,
			(ub4) 1,
			(ub4) 0,
			(OCISnapshot*) NULL,
			(OCISnapshot*) NULL,
			//OCI_DEFAULT ))
			OCI_COMMIT_ON_SUCCESS )) != OCI_SUCCESS)
		{
			// gary Jan.11 2000
			if(status != OCI_NO_DATA && 
				status != OCI_SUCCESS_WITH_INFO)
			{
				_DB_ThrowException(status, m_pDatabase->m_errhp);
                //return status;
			}
		}
		
	}
	else
	{
		if((status = OCIStmtExecute( m_pDatabase->m_svchp,
			m_stmhp,
			m_pDatabase->m_errhp,
			(ub4) 1,
			(ub4) 0,
			(OCISnapshot*) NULL,
			(OCISnapshot*) NULL,
			OCI_DESCRIBE_ONLY )) != OCI_SUCCESS)
		{
			_DB_ThrowException(status, m_pDatabase->m_errhp);
			//return status;
		}
	}
	
	return status;	//gary0128
}


/* called to create associations between select-list variables
and output buffer, execute sql statement, fill all of query
result set into output buffer */
int CRecordset_::FillResultSet(short sType)
{
	//TRC_FUNC("CRecordset_::FillResultSet...Entered");
	
	int status;
	int ret = 0;	//gary0128
	
	try
	{
		Initialize();
	}
	catch(CDBException_ e)
	{
		return e.m_nRetCode;
	}
	
	try
	{
		fflush(stdout);
		PrepareSQL(m_pDatabase->m_sqlstmt);
	}
	catch(CDBException_ e)
	{
		return e.m_nRetCode;
	}
	
	if(sType & (IS_PROCEDURE | IS_FUNCTION))
	{
		if(sType & IS_CURSOR)	//gary0207
			try
		{
			BindByName((text*) P_CURSOR,
				(dvoid*) &m_cursor,
				0,
				SQLT_RSET,
				FALSE );
		}
		catch(CDBException_ e)
		{
			return e.m_nRetCode;
		}
		
		if(sType & IS_FUNCTION)
			try
		{
			BindByName((text*) P_RETURN,
				(dvoid*) &m_pDatabase->m_iRet,
				sizeof(int),
				SQLT_INT,
				FALSE );
		}
		catch(CDBException_ e)
		{
			return e.m_nRetCode;
		}
		
		try
		{
			ret = ExecuteSQL(FALSE);	//gary0128
		}
		catch(CDBException_ e)
		{
			return e.m_nRetCode;
		}
	}
	else
	{
		try
		{
			ExecuteSQL(TRUE);
		}
		catch(CDBException_ e)
		{
			return e.m_nRetCode;
		}
	}
	
	int  nNumCols = 0;
	/* get the number of columns in the select list */
	if((status = OCIAttrGet( (sType & IS_CURSOR) ? m_cursor : m_stmhp,
		(ub4) OCI_HTYPE_STMT,
		&nNumCols,
		(ub4*) 0,
		(ub4) OCI_ATTR_PARAM_COUNT,
		m_pDatabase->m_errhp )) != OCI_SUCCESS)
		return status;
	
	/* create associations between select-list variables and aBindingList */
	CArray_  aBindingList;
	if((status = DescribeColumns(nNumCols, aBindingList, sType)) != OCI_SUCCESS)
	{
		ReleaseArray(aBindingList);
		return status;
	}
	
	if(!(sType & (IS_PROCEDURE | IS_FUNCTION)))
	{
		try
		{
			Initialize();
		}
		catch(CDBException_ e)
		{
			ReleaseArray(aBindingList);
			return e.m_nRetCode;
		}
		
		try
		{
			PrepareSQL(m_pDatabase->m_sqlstmt);
		}
		catch(CDBException_ e)
		{
			ReleaseArray(aBindingList);
			return e.m_nRetCode;
		}
		
		if((status = DefineColumns(aBindingList, FALSE)) != OCI_SUCCESS)
		{
			ReleaseArray(aBindingList);
			return status;
		}
		
		try
		{
			ret = ExecuteSQL(FALSE);	//gary0128
		}
		catch(CDBException_ e)
		{
			ReleaseArray(aBindingList);
			return e.m_nRetCode;
		}
	}
	else
	{
		if((status = DefineColumns(aBindingList, TRUE)) != OCI_SUCCESS)
		{
			ReleaseArray(aBindingList);
			return status;
		}
	}
	
	//gary0128
	if(ret == OCI_NO_DATA || ret == OCI_SUCCESS_WITH_INFO)
	{
		ReleaseArray(aBindingList);
		Cleanup();
		return ret;
	}
	
	if(sType & (IS_PROCEDURE | IS_FUNCTION))
	{
		if((status = OCIStmtFetch(
			m_cursor,
			m_pDatabase->m_errhp,
			1,
			OCI_FETCH_NEXT,
			OCI_DEFAULT )) != OCI_SUCCESS)
		{
			//TRC_INFO("Exit in OCIStmtFetch");
			ReleaseArray(aBindingList);
			Cleanup();
			return status;
		}
	}
	
	do
	{
		CDBRecord_ *pRec = new CDBRecord_();
		if(pRec)
		{
			for(int i=0; i<aBindingList.GetCount(); i++)
			{
				CDBBindingData_ *pBindingData =
					(CDBBindingData_ *)aBindingList[i];
				if(!pBindingData)
					continue;
				
				CVariant_* pVariant = NULL;
				if(pBindingData->m_nType == SQLT_CHR)
				{
					LPSTR lpTmp =
						(LPSTR)pBindingData->m_pDataBuf;
					
					if(lpTmp && strlen(lpTmp)>0)
					{
						int index = strlen(lpTmp)-1;
						while(index>=0 && lpTmp[index]==' ')
						{
							lpTmp[index] = 0;
							index--;
						}
					}
					
					pVariant = new CVariant_(
						pBindingData->m_nType,
						(LPBYTE)lpTmp,
						(strlen(lpTmp)+1)*sizeof(TCHAR));
				}
				else
				{
					pVariant = new CVariant_(
						pBindingData->m_nType,
						pBindingData->m_pDataBuf,
						pBindingData->m_nRealDataLen);
				}
				
				if(pVariant)
				{
					pRec->AddDataItem(pVariant);
					pBindingData->Clear();
				}
			}
		}
		
		AddRecord(pRec);
		
		try
		{
			status = FetchNext(sType & IS_CURSOR);
		}
		catch(CDBException_ e)
		{
			status = e.m_nRetCode;
		}
	}
	while(!status);
	
	ReleaseArray(aBindingList);
	
	Cleanup();
	
	//TRC_FUNC("CRecordset_::FillResultSet...Returned");
	
	return DB_SUCCESS;
}

void CRecordset_::ReleaseArray(CArray_ &aBindingList)
{
	while(aBindingList.GetCount() > 0)
	{
		CDBBindingData_* pBindingData =
			(CDBBindingData_*)aBindingList[0];
		aBindingList.RemoveAt(0);
		if(pBindingData)
			delete pBindingData;
	}
}

/* Called to fetch query result */
int  CRecordset_::FetchNext(BOOL bIsCursorStmt)
{
	int status;
	if((status = OCIStmtFetch( 
		bIsCursorStmt ? m_cursor : m_stmhp,
		m_pDatabase->m_errhp,
		(ub4) 1,
		(ub2) OCI_FETCH_NEXT,
		OCI_DEFAULT )) != OCI_SUCCESS)
	{
		if(status != OCI_NO_DATA && status != OCI_SUCCESS_WITH_INFO)
		{
			_DB_ThrowException(status, m_pDatabase->m_errhp);
			//return status;
		}
	}
	
	return status;
}


/* Called to get column count */
int  CRecordset_::GetColumnCount()
{
	return m_aColDescriptors.GetCount();
}


/* Called to get name of column by nColIndex */
LPSTR CRecordset_::GetColumnName(int nColIndex)
{
	if(nColIndex >=0 && nColIndex <m_aColDescriptors.GetCount())
	{
		CDBColumnDescriptor_ *pColDesc =
			(CDBColumnDescriptor_ *)m_aColDescriptors[nColIndex];
		
		if(pColDesc)
			return pColDesc->GetName();
	}
	
	/* fail */
	return NULL;
}


/* Called to get data type of column by nColIndex */
ub2  CRecordset_::GetColumnType(int nColIndex)
{
	if(nColIndex >=0 && nColIndex <m_aColDescriptors.GetCount())
	{
		CDBColumnDescriptor_ *pColDesc =
			(CDBColumnDescriptor_ *)m_aColDescriptors[nColIndex];
		
		if(pColDesc)
			return pColDesc->GetDataType();
	}
	
	/* fail */
	return 0;
}


/* Called to get data size of column by nColIndex */
int  CRecordset_::GetColumnSize(int nColIndex)
{
	if(nColIndex >=0 && nColIndex <m_aColDescriptors.GetCount())
	{
		CDBColumnDescriptor_ *pColDesc =
			(CDBColumnDescriptor_ *)m_aColDescriptors[nColIndex];
		
		if(pColDesc)
			return pColDesc->GetMaxSize();
		
	}
	
	/* fail */
	return 0;
}


/* Called to get record count */
int  CRecordset_::GetRecordCount()
{
	return m_aRecords.GetCount();
}


/* Called to get record by nRecIndex */
CDBRecord_ *CRecordset_::GetRecord(int nRecIndex)
{
	if(nRecIndex >=0 && nRecIndex < m_aRecords.GetCount())
	{
		return (CDBRecord_ *)m_aRecords[nRecIndex];
	}
	
	return NULL;
}


/* called to create associations between select-list variables
and outbuffer */
int  CRecordset_::DefineColumns(CArray_ &aBindingList, BOOL bIsCursorStmt)
{
	for(int i=0; i<aBindingList.GetCount(); i++)
	{
		CDBBindingData_ *pBindingData =
			(CDBBindingData_ *)aBindingList[i];
		
		ub2 nType = (ub2) pBindingData->m_nType;
		if(nType == SQLT_NUM)
			nType = (ub2) SQLT_VNU;
		else if(nType == SQLT_DAT)
			nType = (ub2) SQLT_ODT;
		
		try
		{
			DefineByPos( i+1,
				(dvoid*) pBindingData->m_pDataBuf,
				(ub4) pBindingData->m_nRealDataLen,
				nType, bIsCursorStmt );
		}
		catch(CDBException_ e)
		{
			return e.m_nRetCode;
		}
	}
	
	return  DB_SUCCESS;
}


/* called to get column descriptors information */
int  CRecordset_::DescribeColumns(int nNumCols, CArray_ &aBindingList,
								  short sType)
{
	int  	status =0, i;
	text	*col_name;
	ub4		col_name_len;
	ub2		col_data_size;
	ub2		col_data_type;
	
	
	/* go through the column list and retrieve the data type of each column */
	for(i=0; i<nNumCols; i++)
	{
		/* get parameter for column */
		/* Procedure: i+1;  Function: i */
		status = OCIParamGet( 
			(sType & IS_CURSOR) ? m_cursor : m_stmhp, 
			(ub4) OCI_HTYPE_STMT,
			m_pDatabase->m_errhp,
			(dvoid**) &m_colhp,
			(ub4) (sType & IS_FUNCTION) ? i : i+1 );
		if(status || !m_colhp)
			return status;
		
		/* get name of column i */
		if((status = OCIAttrGet((dvoid*) m_colhp,
			(ub4) OCI_DTYPE_PARAM,
			(dvoid*) &col_name,
			(ub4*) &col_name_len,
			(ub4) OCI_ATTR_NAME,
			m_pDatabase->m_errhp )) != OCI_SUCCESS)
			return status;
		
		/* get data type of column i */
		if((status = OCIAttrGet((dvoid*) m_colhp,
			(ub4) OCI_DTYPE_PARAM,
			(dvoid*) &col_data_type,
			(ub4*) 0,
			(ub4) OCI_ATTR_DATA_TYPE,
			m_pDatabase->m_errhp )) != OCI_SUCCESS)
			return status;
		
		/* get max data size of column i */
		if((status = OCIAttrGet((dvoid*) m_colhp,
			(ub4)OCI_DTYPE_PARAM,
			(dvoid*) &col_data_size,
			(ub4*) 0,
			(ub4) OCI_ATTR_DATA_SIZE,
			m_pDatabase->m_errhp )) != OCI_SUCCESS)
			return status;
		
		CDBColumnDescriptor_ *pColDesc = 
			new CDBColumnDescriptor_( (char*) col_name, 
			(unsigned int) col_name_len,
			(short unsigned int) col_data_type, 
			(int) col_data_size);
		
		if(pColDesc)
			AddColumnDescriptor(pColDesc);
		
		CDBBindingData_ *pBindingData =
			new CDBBindingData_(col_data_type, NULL, col_data_size);
		
		if(pBindingData)
			aBindingList.Add(pBindingData, TRUE);
		
		/* define by position */
	}
	
	return 	status;
}


/* Called to add a column descriptor */
void CRecordset_::AddColumnDescriptor(CDBColumnDescriptor_ *pColDesc)
{
	if(pColDesc)
		m_aColDescriptors.Add(pColDesc);
}


/* Called to add a record */
void CRecordset_::AddRecord(CDBRecord_ *pRecord)
{
	if(pRecord)
		m_aRecords.Add(pRecord);
}


/*--------------------------------------------------------------*/
/*                                                              */
/*      class CDBColumnDescriptor                               */
/*                                                              */
/*--------------------------------------------------------------*/
CDBColumnDescriptor_::CDBColumnDescriptor_(LPSTR lpszName,
										   ub4 col_name_len, ub2 nDataType, int nMaxSize)
{
	if(!lpszName)
		strcpy(m_szName, "");
	else
	{
		strncpy(m_szName, lpszName, col_name_len);
		m_szName[col_name_len] = 0;
	}
	
	m_nDataType = nDataType;
	m_nMaxSize = nMaxSize;
}

CDBColumnDescriptor_::~CDBColumnDescriptor_()
{
}


/* Called to get name of column */
LPSTR CDBColumnDescriptor_::GetName()
{
	return (LPSTR)m_szName;
}

/* Called to get data type of column */
ub2 CDBColumnDescriptor_::GetDataType()
{
	return m_nDataType;
}

/* Called to get data size of column */
int CDBColumnDescriptor_::GetMaxSize()
{
	return m_nMaxSize;
}


/*--------------------------------------------------------------*/
/*                                                              */
/*      class CDBBindingData_									*/
/*                                                              */
/*--------------------------------------------------------------*/
CDBBindingData_::CDBBindingData_(ub2 nType, LPVOID pData, int len)
{
	m_nType = nType;
	m_pDataBuf = NULL;
	
	if(nType == SQLT_NUM || nType == SQLT_DAT)
	{
		if(nType == SQLT_NUM)
		{
			m_nMaxDataLen = sizeof(OCINumber);
			OCINumber *pnumber = new OCINumber();
			m_pDataBuf = (LPBYTE)pnumber;
		}
		else
		{
			m_nMaxDataLen = sizeof(OCIDate); 
			OCIDate *ptime = new OCIDate();
			m_pDataBuf = (LPBYTE)ptime;
		}
		
		m_nRealDataLen = m_nMaxDataLen;
		
		
		if(pData && m_pDataBuf)
		{
			memcpy(m_pDataBuf, pData, m_nMaxDataLen);
		}
		else if(m_pDataBuf)
		{
			memset(m_pDataBuf, 0, m_nMaxDataLen);
		}
	}
	else
	{
		if(nType == SQLT_CHR || nType == SQLT_DAT)
			m_nMaxDataLen = len+1;
		else
			m_nMaxDataLen = len;
		
		m_pDataBuf = NULL;
		m_nRealDataLen = len;
		
		if(len > 0)
		{
			m_pDataBuf = new BYTE[m_nMaxDataLen];
			if(pData && m_pDataBuf)
			{
				memcpy(m_pDataBuf, pData, m_nMaxDataLen);
			}
			else if(m_pDataBuf)
			{
				memset(m_pDataBuf, 0, m_nMaxDataLen);
			}
			
			if(nType == SQLT_CHR)
				m_pDataBuf[m_nMaxDataLen-1] = 0;
		}
	}
}

CDBBindingData_::~CDBBindingData_()
{
	if(m_pDataBuf)
		//		delete m_pDataBuf;		//possible memory leak HERE
		
		//gary20000510	modified
	{
		if(m_nType == SQLT_NUM)
		{
			OCINumber *pnumber = (OCINumber *)m_pDataBuf;
			delete pnumber;
			m_pDataBuf = NULL;
		}
		else if(m_nType == SQLT_DAT)
		{
			OCIDate *ptime = (OCIDate *)m_pDataBuf;
			delete ptime;
			m_pDataBuf = NULL;
		}
		else
		{
			delete [] m_pDataBuf;
			m_pDataBuf = NULL;
		}
	}
}

/* Called to clear up data buffer */
void CDBBindingData_::Clear()
{
	if(m_pDataBuf && m_nMaxDataLen>0)
	{
		memset(m_pDataBuf, 0, m_nMaxDataLen);
	}
}


/*--------------------------------------------------------------*/
/*                                                              */
/*      class CDBRecord_										*/
/*                                                              */
/*--------------------------------------------------------------*/
CDBRecord_::CDBRecord_()
{
}

CDBRecord_::~CDBRecord_()
{
	while(m_aDataItems.GetCount() > 0)
	{
		CVariant_* pItem = (CVariant_*)m_aDataItems[0];
		m_aDataItems.RemoveAt(0);
		if(pItem)
			delete pItem;
	}
}


/* Called to get data item count */
int CDBRecord_::GetItemCount()
{
	return m_aDataItems.GetCount();
}

/* Called to get a data item by nColIndex */
CVariant_* CDBRecord_::GetDataItem(int nColIndex)
{
	if(nColIndex <0 || nColIndex >= m_aDataItems.GetCount())
		return NULL;
	
	return (CVariant_*)m_aDataItems[nColIndex];
}

/* Called to add a data item */
void CDBRecord_::AddDataItem(CVariant_* pItem)
{
	if(pItem)
		m_aDataItems.Add(pItem);
}


/*--------------------------------------------------------------*/
/*                                                              */
/*      class CVariant_                                         */
/*                                                              */
/*--------------------------------------------------------------*/
CVariant_::CVariant_()
{
	m_nType = 0;
}

CVariant_::CVariant_(short nType, LPBYTE pData, DWORD dwSize)
{
	m_nType = nType;
	switch(m_nType)
	{
	case SQLT_INT:
		m_iVal = *(int*)pData;
		break;
	case SQLT_UIN:
		m_uiVal = *(UINT*)pData;
		break;
	case SQLT_FLT:
		m_fltVal = *(double*)pData;
		break;
	case SQLT_DAT:
		if(dwSize > sizeof(OCIDate))
			dwSize = sizeof(OCIDate);
		memcpy((char*) &m_time, (char*) pData, dwSize);
		break;
	case SQLT_NUM:
		if(dwSize > sizeof(OCINumber))
			dwSize = sizeof(OCINumber);
		memcpy((char*) &m_number, (char*) pData, dwSize);
		break;
	case SQLT_CHR:
		if(pData)
		{
			m_pString = new TCHAR[strlen((LPSTR)pData)+1];
			if(m_pString)
				strcpy(m_pString, (LPSTR)pData);
		}
		else
			m_pString = NULL;
		break;
	case SQLT_AFC:
		m_char = *(char*)pData;
		break;
	case SQLT_BIN:
		if(pData)
		{
			m_pBinary = new CBinary_();
			if(m_pBinary)
				m_pBinary->CopyData(pData, dwSize);
		}
		else
			m_pBinary = NULL;
		break;
	case SQLT_PDN:
		break;
	}
}

CVariant_::~CVariant_()
{
	Clear();
}

void CVariant_::Clear()
{
	if(m_nType == SQLT_CHR)
	{
		if(m_pString)
			delete [] m_pString;
	}
	
	if(m_nType == SQLT_BIN)
	{
		if(m_pBinary)
			delete m_pBinary;
	}
	
	m_nType = 0;
}

CVariant_& CVariant_::operator = (CVariant_& other)
{
	Clear();
	
	m_nType = other.m_nType;
	switch(m_nType)
	{
	case SQLT_INT:
		m_iVal = other.m_iVal;
		break;
	case SQLT_UIN:
		m_uiVal = other.m_uiVal;
		break;
	case SQLT_FLT:
		m_fltVal = other.m_fltVal;
		break;
	case SQLT_DAT:
		memcpy((char*) &m_time, (char*) &other.m_time, sizeof(OCIDate));
		break;
	case SQLT_NUM:
		memcpy((char*) &m_number, (char*) &other.m_number, sizeof(OCINumber));
		break;
	case SQLT_CHR:
		if(other.m_pString)
		{
			m_pString = new TCHAR[strlen(other.m_pString)+1];
			if(m_pString)
				strcpy(m_pString, other.m_pString);
		}
		else
			m_pString = NULL;
		break;
	case SQLT_BIN:
		if(other.m_pBinary)
		{
			m_pBinary = new CBinary_();
			if(m_pBinary)
				(*m_pBinary) = (*other.m_pBinary);
		}
		else
			m_pBinary = NULL;
		break;
	case SQLT_PDN:
		break;
	}
	
	return *this;
}

void CVariant_::SetValue(short nType, LPBYTE pData, DWORD dwSize)
{
	Clear();
	m_nType = nType;
	if(!pData || dwSize==0) return;
	
	switch(m_nType)
	{
	case SQLT_INT:
		m_iVal = *(int*)pData;
		break;
	case SQLT_UIN:
		m_uiVal = *(UINT*)pData;
		break;
	case SQLT_FLT:
		m_fltVal = *(double*)pData;
		break;
	case SQLT_DAT:
		if(dwSize > sizeof(OCIDate))
			dwSize = sizeof(OCIDate);
		memcpy((char*) &m_time, (char*) pData, dwSize);
		break;
	case SQLT_NUM:
		if(dwSize > sizeof(OCINumber))
			dwSize = sizeof(OCINumber);
		memcpy((char*) &m_number, (char*) pData, dwSize);
		break;
	case SQLT_CHR:
		m_pString = new TCHAR[strlen((LPSTR)pData)+1];
		if(m_pString)
			strcpy(m_pString, (LPSTR)pData);
		break;
	case SQLT_BIN:
		m_pBinary = new CBinary_();
		if(m_pBinary)
			m_pBinary->CopyData(pData, dwSize);
		break;
	case SQLT_PDN:
		break;
	}
}

void CVariant_::GetValue(short* pnType, LPBYTE* ppData, DWORD* pdwSize)
{
	* pnType = m_nType;
	* pdwSize = 0;
	* ppData = NULL;
	switch(m_nType)
	{
	case SQLT_INT:
		* ppData = (LPBYTE)&m_iVal;
		* pdwSize = sizeof(int);
		break;
	case SQLT_UIN:
		* ppData = (LPBYTE)&m_uiVal;
		* pdwSize = sizeof(UINT);
		break;
	case SQLT_FLT:
		* ppData = (LPBYTE)&m_fltVal;
		* pdwSize = sizeof(double);
		break;
	case SQLT_NUM:
		* ppData = (LPBYTE)&m_number;
		* pdwSize = sizeof(OCINumber);
		break;
	case SQLT_DAT:
		* ppData = (LPBYTE)&m_time;
		* pdwSize = sizeof(OCIDate);
		break;
	case SQLT_CHR:
		* ppData = (LPBYTE)m_pString;
		if(m_pString)
			* pdwSize = (strlen(m_pString)+1)*sizeof(TCHAR);
		break;
	case SQLT_AFC:
		* ppData = (LPBYTE)&m_char;
		* pdwSize = sizeof(char);
		break;
	case SQLT_BIN:
		if(m_pBinary)
		{
			* ppData = m_pBinary->m_pData;
			* pdwSize = m_pBinary->m_dwSize;
		}
		break;
	case SQLT_PDN:
		break;
	}
}


/*--------------------------------------------------------------*/
/*                                                              */
/*      class CArray_                                           */
/*                                                              */
/*--------------------------------------------------------------*/
CArray_::CArray_()
{
	m_ppHead = NULL;
	m_nAlloc = 0;
	m_nUsed  = 0;
}

CArray_::CArray_(LPVOID* ppHead, int nSize)
{
	m_ppHead = NULL;
	m_nAlloc = 0;
	m_nUsed  = 0;
	
	if(ppHead != NULL)
	{
		m_ppHead = new LPVOID[nSize];
		if(m_ppHead)
		{
			memcpy(m_ppHead, ppHead, sizeof(LPVOID)*nSize);
			m_nAlloc = nSize;
			m_nUsed  = nSize;
		}
	}
}

CArray_::~CArray_()
{
	if(m_ppHead)
		delete []m_ppHead;
}

BOOL CArray_::Add(LPVOID lpv, BOOL bCheckDuplicate)
{
	if(!lpv)	return FALSE;
	
	if(Expand())
	{
		if(bCheckDuplicate && GetIndex(lpv) >= 0)
			return FALSE;
		
		m_ppHead[m_nUsed++] = lpv;
		return TRUE;
	}
	
	return FALSE;
}

BOOL CArray_::InsertAt(int nIndex, LPVOID lpv)
{
	if(nIndex >= 0 && nIndex <= m_nUsed)
	{
		if(!Expand())
			return FALSE;
		
		if(nIndex < m_nUsed)
			memmove(&m_ppHead[nIndex + 1], &m_ppHead[nIndex],
			sizeof(LPVOID)*(m_nUsed - nIndex));
		
		m_ppHead[nIndex] = lpv;
		m_nUsed++;
		
		return TRUE;
	}
	
	return FALSE;
}

BOOL CArray_::SetAt(int nIndex, LPVOID lpv)
{
	if (nIndex >= 0 && nIndex < m_nUsed)
	{
		m_ppHead[nIndex] = lpv;
		
		return TRUE;
	}
	
	return FALSE;
}

BOOL CArray_::Remove(LPVOID lpv)
{
	int i;
	
	if(!lpv)        return FALSE;
	
	for(i = 0; i < m_nUsed; i++)
		if(m_ppHead[i] == lpv)
			break;
		
		if (i < m_nUsed)
		{
			// found
			if(i < m_nUsed - 1)
				memcpy(&m_ppHead[i], &m_ppHead[i+1],
				sizeof(LPVOID)*(m_nUsed - i - 1));
			m_nUsed--;
			return  TRUE;
		}
		
		return  FALSE;
}

BOOL CArray_::RemoveAt(int i)
{
	if(i < m_nUsed)
	{
		if(i < m_nUsed - 1)
			memcpy(&m_ppHead[i], &m_ppHead[i+1],
			sizeof(LPVOID)*(m_nUsed - i - 1));
		m_nUsed--;
		return  TRUE;
	}
	
	return  FALSE;
}

void CArray_::RemoveAll()
{
	if(m_ppHead)
		delete []m_ppHead;
	m_ppHead = NULL;
	m_nAlloc = 0;
	m_nUsed = 0;
}

CArray_* CArray_::Clone()
{
	return new CArray_(m_ppHead, m_nUsed);
}

LPVOID* CArray_::GetData()
{
	return m_ppHead;
}

int CArray_::GetCount()
{
	return m_nUsed;
}

LPVOID CArray_::operator [](int i)
{
	if(i >= 0 && i < m_nUsed)
		return m_ppHead[i];
	
	return NULL;
}

int CArray_::GetIndex(LPVOID lpv)
{
	for(int i = 0; i < m_nUsed; i++)
		if(m_ppHead[i] == lpv)
			return i;
		
		return -1;
}

BOOL CArray_::Expand()
{
	if(m_nUsed >= m_nAlloc)
	{
		LPVOID* ppNew = new LPVOID[m_nAlloc + DELTA];
		if(ppNew)
		{
			if(m_ppHead)
			{
				memcpy(ppNew, m_ppHead, 
					sizeof(LPVOID)*m_nAlloc);
				delete []m_ppHead;
			}
			m_ppHead = ppNew;
			m_nAlloc += DELTA;
			return TRUE;
		}
		return FALSE;
	}
	return TRUE;
}

////////////////////////////////Add for Statment Binding//////////////////////////
CDBPreStmt_::CDBPreStmt_(CDatabase_* pDB, LPCSTR pszSQLStmt)
{
	m_pDB = pDB;
	
	if(pszSQLStmt != NULL)
	{
		int nSQLLen = strlen((char*)pszSQLStmt);
		m_pszSQLStmt = new BYTE[nSQLLen + 1];
		m_pszSQLStmt[nSQLLen] = '\0';
		strcpy((char*)m_pszSQLStmt, pszSQLStmt);
	}
	else
		m_pszSQLStmt = NULL;

	for(int i=0; i<_MAX_PARAMETERS; i++ )
		m_Indicator[i] = 0;
	
	m_nIndicatorIndex = 0;
}

CDBPreStmt_::~CDBPreStmt_()
{
	if(m_pszSQLStmt != NULL)
		delete[] m_pszSQLStmt;
}

// For SQL & Procedure
void CDBPreStmt_::BindInParamByName(LPCSTR pszParamName, DWORD &dwContent)
{
	RT_ASSERTE(pszParamName != NULL);
	
	sword status;
	OCIBind  *bndhp  = (OCIBind*)   0;
	
	RT_ASSERTE_RETURN_VOID(m_nIndicatorIndex <_MAX_PARAMETERS);
	status = OCIBindByName(m_pDB->m_stmhp,
		&bndhp,
		m_pDB->m_errhp,
		(text*)(pszParamName),
		(sb4)(strlen((char*)pszParamName)),
		(dvoid*)&dwContent,
		(sb4)(sizeof(DWORD)),
		SQLT_INT,
		&m_Indicator[m_nIndicatorIndex++],
		0,
		NULL,	
		0,	
		NULL,
		OCI_DEFAULT);
	
	if (status != OCI_SUCCESS)
	{
		_DB_ThrowException(status, m_pDB->m_errhp);
	}	
}


// For SQL & Procedure
void CDBPreStmt_::BindInParamByName(LPCSTR pszParamName, LPBYTE pszContent)
{
	RT_ASSERTE(pszParamName != NULL);
	
	sword status;
	OCIBind  *bndhp  = (OCIBind*)   0;
	
	RT_ASSERTE_RETURN_VOID(m_nIndicatorIndex <_MAX_PARAMETERS);
	if(pszContent == NULL)
	{
		m_Indicator[m_nIndicatorIndex] = -1;
		status = OCIBindByName(m_pDB->m_stmhp,
			&bndhp,
			m_pDB->m_errhp,
			(text*)(pszParamName),
			(sb4)(strlen((char*)pszParamName)),
			NULL,
			(sb4)0,
			SQLT_STR,
			&m_Indicator[m_nIndicatorIndex++],
			0,
			NULL,	
			0,	
			NULL,
			OCI_DEFAULT);
		
		if (status != OCI_SUCCESS)
		{
			_DB_ThrowException(status, m_pDB->m_errhp);
		}		
	}
	else
	{
		RT_ASSERTE(strlen((char*)pszContent) < MAX_CONTENT_LEN);
		
		status = OCIBindByName(m_pDB->m_stmhp,
			&bndhp,
			m_pDB->m_errhp,
			(text*)(pszParamName),
			(sb4)(strlen((char*)pszParamName)),
			(dvoid*)pszContent,
			(sb4)(MAX_CONTENT_LEN),
			SQLT_STR,
			&m_Indicator[m_nIndicatorIndex++],
			0,
			NULL,	
			0,	
			NULL,
			OCI_DEFAULT);
		
		if (status != OCI_SUCCESS)
		{
			_DB_ThrowException(status, m_pDB->m_errhp);
		}	
	}
}

// For Procedure
void CDBPreStmt_::BindOutParamByName(LPCSTR pszParamName, DWORD &dwContent)
{
	RT_ASSERTE(pszParamName != NULL);
	
	sword status;
	OCIBind  *bndhp  = (OCIBind*)   0;

	RT_ASSERTE_RETURN_VOID(m_nIndicatorIndex <_MAX_PARAMETERS);
	status = OCIBindByName(m_pDB->m_stmhp,
		&bndhp,
		m_pDB->m_errhp,
		(text*)(pszParamName),
		(sb4)(strlen((char*)pszParamName)),
		(dvoid*)&dwContent,
		(sb4)(sizeof(DWORD)),
		SQLT_INT,
		&m_Indicator[m_nIndicatorIndex++],
		0,
		NULL,	
		0,	
		NULL,
		OCI_DEFAULT);
	
	if (status != OCI_SUCCESS)
	{
		_DB_ThrowException(status, m_pDB->m_errhp);
	}	
}

// For Procedure
void CDBPreStmt_::BindOutParamByName(LPCSTR pszParamName, LPBYTE pszContent)
{
	RT_ASSERTE(pszParamName != NULL);
	RT_ASSERTE(pszContent != NULL);
	
	sb2 indicator;	//Content is NULL, indicator = -1, else indicator = 0
	sword status;
	OCIBind  *bndhp  = (OCIBind*)   0;
	
	RT_ASSERTE_RETURN_VOID(m_nIndicatorIndex <_MAX_PARAMETERS);
	if(pszContent == NULL)
	{
		m_Indicator[m_nIndicatorIndex] = -1;

		status = OCIBindByName(m_pDB->m_stmhp,
			&bndhp,
			m_pDB->m_errhp,
			(text*)(pszParamName),
			(sb4)(strlen((char*)pszParamName)),
			(dvoid*)NULL,
			(sb4)0,
			SQLT_STR,
			&m_Indicator[m_nIndicatorIndex++],
			0,
			NULL,	
			0,	
			NULL,
			OCI_DEFAULT);
		
		if (status != OCI_SUCCESS)
		{
			_DB_ThrowException(status, m_pDB->m_errhp);
		}
	}
	else
	{
		indicator = 0;
		
		status = OCIBindByName(m_pDB->m_stmhp,
			&bndhp,
			m_pDB->m_errhp,
			(text*)(pszParamName),
			(sb4)(strlen((char*)pszParamName)),
			(dvoid*)pszContent,
			(sb4)MAX_CONTENT_LEN,
			SQLT_STR,
			&m_Indicator[m_nIndicatorIndex++],
			0,
			NULL,	
			0,	
			NULL,
			OCI_DEFAULT);
		
		if (status != OCI_SUCCESS)
		{
			_DB_ThrowException(status, m_pDB->m_errhp);
		}	
	}
}

#endif
